#!/usr/bin/env python
# -*- coding: utf-8 -*-

import bisect
from PyQt4.QtCore import *
from PyQt4.QtGui import *

KEY, NODE = range(2)

class Node(object):

    def __init__(self, name, fields=[], orderFieldIndex=-1, parent=None):
        self.parent 	     = parent
        self.name   	     = name
        self.fields 	     = fields
        self.orderFieldIndex = orderFieldIndex

    def isComplex(self):
        return False

    def orderKey(self):
        if self.orderFieldIndex >= 0 and self.orderFieldIndex < self.fieldsCount():
            return self.field(self.orderFieldIndex).lower()
        return self.name.lower()

    def toString(self, separator="\t"):
        return self.name + separator + separator.join(self.fields)

    def __len__(self):
        return len(self.fields)

    def fieldsCount(self):
        return len(self.fields)

    def field(self, column):
        assert 0 <= column < len(self.fields)
        return self.fields[column]

class ComplexNode(Node):

    def __init__(self, name, fields=[], orderFieldIndex=-1, parent=None):
        super(ComplexNode, self).__init__(name, fields, orderFieldIndex, parent)
        self.children = []

    def isComplex(self):
        return True

    def childrenCount(self):
        return len(self.children)

    def childAtRow(self, row):
        return self.children[row][NODE]
        
    def rowOfChild(self, child):
        for i, item in enumerate(self.children):
            if item[NODE] == child:
                return i
        return -1

    def childWithKey(self, key):
        if not self.children:
            return None
        i = bisect.bisect_left(self.children, (key, None))
        if i < 0 or i >= self.childrenCount():
            return None
        if self.children[i][KEY] == key:
            return self.children[i][NODE]
        return None

    def insertChild(self, child):
        child.parent = self
        bisect.insort(self.children, (child.orderKey(), child))

    def delChild(self, child):
        child.parent = None
        row          = self.rowOfChild(child)
        self.children.remove(self.children[row])

class TreeOfTableModel(QAbstractItemModel):

    def __init__(self, parent=None):
        super(TreeOfTableModel, self).__init__(parent)
        self.columns = 0
        self.root = ComplexNode("")
        self.headers = []

    def rowCount(self, parent):
        node = self.nodeFromIndex(parent)
        if node is None:
            return 0
	
        if isinstance(node, ComplexNode):
            return node.childrenCount()
	
        return 0

    def columnCount(self, parent):
        return self.columns

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal and \
           role == Qt.DisplayRole:
            assert 0 <= section <= len(self.headers)
            return QVariant(self.headers[section])
        return QVariant()


    def index(self, row, column, parent):
        assert self.root
        branch = self.nodeFromIndex(parent)
        assert branch is not None
        return self.createIndex(row, column,
                                branch.childAtRow(row))

    def parent(self, child):
        node = self.nodeFromIndex(child)
        if node is None:
            return QModelIndex()
        parent = node.parent
        if parent is None:
            return QModelIndex()
        grandparent = parent.parent
        if grandparent is None:
            return QModelIndex()
        row = grandparent.rowOfChild(parent)
        assert row != -1
        return self.createIndex(row, 0, parent)


    def nodeFromIndex(self, index):
        return index.internalPointer() \
            if index.isValid() else self.root